package com.qyxx.platform.gsmng.common.service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
import org.apache.commons.lang.StringUtils;
import org.hibernate.SQLQuery;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.qyxx.platform.common.orm.hibernate.HibernateDao;
import com.qyxx.platform.gsc.cache.SqlCache;
import com.qyxx.platform.gsc.utils.Constants;
import com.qyxx.platform.gsmng.common.dao.ArgPreparedStatementSetter;
import com.qyxx.platform.gsmng.common.dao.GsMngDao;
import com.qyxx.platform.gsmng.common.dao.ProcessInfoDao;
import com.qyxx.platform.gsmng.common.dao.ProcessModelInfoDao;
import com.qyxx.platform.gsmng.common.entity.ProcessInfo;
import com.qyxx.platform.gsmng.common.entity.ProcessModelInfo;
import com.qyxx.platform.sysmng.accountmng.dao.RoleDao;
import com.qyxx.platform.sysmng.accountmng.dao.UserDao;
import com.qyxx.platform.sysmng.accountmng.entity.Organization;
import com.qyxx.platform.sysmng.accountmng.entity.Role;
import com.qyxx.platform.sysmng.accountmng.entity.User;
import com.qyxx.platform.sysmng.exception.GsException;
/**
 *数据下推处理类
 */
@Service
@Transactional
public class DataDeal extends HibernateDao<Object, Long> {
	
	private static final String INSERT = "insert into CAIGOU_HETONG(VERSION,CREATE_USER,CREATE_TIME,CG_CODE) (select a.VERSION,a.CREATE_USER,a.CREATE_TIME,a.CONTRACT_NO from MAIN_TABLE a where a.id=:id);"; 
	
	private static final String INSERT2 = "insert into KEHUXINXI(VERSION,CREATE_USER,CREATE_TIME,CODE,MING)  (select a.VERSION,a.CREATE_USER,a.CREATE_TIME,a.CONTRACT_NO,a.CONTRACT_CUSTOMERNAME from MAIN_TABLE a where a.id=:id);";

	private static final String UPDATE = "UPDATE MAIN_TABLE SET CONTRACT_CUSTOMERNAME=:type where ID=:id;";
	
	private static final Map<String, String> sqlMap = new HashMap<String, String>();
	
	private ProcessInfoDao processInfoDao;
	
	private ProcessModelInfoDao processModelInfoDao;
	
	private RoleDao roleDao;
	
	private UserDao userDao;
	static {
		sqlMap.put("INSERT", INSERT);
		sqlMap.put("INSERT2", INSERT2);
		sqlMap.put("UPDATE", UPDATE);
	}
	private GsMngDao gsMngDao;
	
	private HistoryService historyService;
	
	protected TaskService taskService;	

	
	@Autowired
	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}
	@Autowired
	public void setHistoryService(HistoryService historyService) {
		this.historyService = historyService;
	}

	@Autowired
	public void setGsMngDao(GsMngDao gsMngDao) {
		this.gsMngDao = gsMngDao;
	}

	@Autowired
	public void setRoleDao(RoleDao roleDao) {
		this.roleDao = roleDao;
	}
	
	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setProcessInfoDao(ProcessInfoDao processInfoDao) {
		this.processInfoDao = processInfoDao;
	}

	@Autowired
	public void setProcessModelInfoDao(
			ProcessModelInfoDao processModelInfoDao) {
		this.processModelInfoDao = processModelInfoDao;
	}

	/**
	 * 数据下推方法规则
	 * 
	 * @param sourceModel --- contracts.MainTable
	 * @param targetModel --- caigoushang.CaiGouShangZhuBiao1
	 * @param ruleName --- 模块.key
	 * @param roleName ---角色名
	 */
	@Transactional
	public void createOrder(ActivityExecution execution,String sourceModel,String targetModel,String ruleName,String roleName){
		String businessKey = execution.getProcessBusinessKey();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		Long bid = Long.valueOf(a[1]);// 单据ID
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("id",bid );
		//HistoricProcessInstance hpi = historyService.createHistoricProcessInstanceQuery().processInstanceId(execution.getProcessInstanceId()).singleResult();
		//loginName=hpi.getStartUserId();//设置下推数据的拥有者
	
		String	loginName= (String) execution.getVariable("startUser");
	
		User user = userDao.findUniqueBy("loginName", loginName);
		Role r = roleDao.findUniqueBy("roleName", roleName);
		List<User> userList = r.getUserList();
		Long userId = null;
		Organization onwerOrg =user.getOrganization();
		String onwerCode = onwerOrg.getOrganizationCode();
		for(User u : userList){
			if(u.getId()==user.getId()){
				userId = u.getId();
				break;
			}else{
				Organization org =u.getOrganization();
				String code = org.getOrganizationCode();
				if(onwerCode.indexOf(code)>=0 || code.indexOf(onwerCode)>=0){
					userId = u.getId();
					break;
				}
			}
		}
		if(userId!=null){
			paramMap.put("createUser",userId);
		}else{
			userId = userList.get(0).getId();	
			paramMap.put("createUser",userId);
		}
		paramMap.put("status",GsMngManager.STATUS_DRAFT);
		paramMap.put("createTime",new Timestamp(new Date().getTime()));
		paramMap.put("versions",1L);
		List<Long> listId = new ArrayList<Long>();
		// getSession().createSQLQuery(INSERT).setLong(0, bid).executeUpdate();
		// 根据SQL语句条件下推数据
		String sqlKey = Constants.RULE_SUFFIX + Constants.NAME_SPLIT_SYMBOL + ruleName;
		final String namedSql = SqlCache.getInstance().getSqlContent(sqlKey);
		if(StringUtils.isBlank(namedSql)) {
			throw new GsException(sqlKey + "对应的sql找不到");
		}
		// final String namedSql= sqlMap.get(type);
		/*Work work = new Work() {

			public void execute(Connection connection)
														throws SQLException {
				// 通过JDBC API执行用于批量更新的SQL语句
				PreparedStatement stmt = null;
				ResultSet rs = null;
				try {
					String sql = NamedParameterUtils.parseSqlStatementIntoString(namedSql);
					Object[] args = NamedParameterUtils.buildValueArray(namedSql, paramMap);
					stmt = connection.prepareStatement(sql,
							new String[] { "ID" });
					//stmt.setLong(1, bid);
					ArgPreparedStatementSetter aps = new ArgPreparedStatementSetter(args);
					aps.setValues(stmt);
					stmt.executeUpdate();
					rs = stmt.getGeneratedKeys();
					if(rs!=null){
						while(rs.next()) {
							Long id = (long) rs.getInt(1);
							listId.add(id);
						}
					}
				} finally {
					if (rs != null) {
						try {
							rs.close();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					if (stmt != null) {
						try {
							stmt.close();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		};
		
		getSession().doWork(work);*/
		listId = gsMngDao.insertDataWithReturnKeys(namedSql, paramMap);
	

		//String callActivityProcess =targetModel+ "|||" + listId;//存在子流程使用的变量
		//execution.setVariable("varOutOrder", callActivityProcess);
		
		execution.setVariable("targetModel", targetModel);
		execution.setVariable("createUser", userId);			
		execution.setVariable("masterIdList", listId);
/*		Role r = roleDao.findUniqueBy("roleName", roleName);
		List<User> userList = r.getUserList();
		if(userList.size()>0){
			Long userId = userList.get(0).getId();
			String hql = "update "+targetModel+" set "+GsMngManager.CREATE_USER+" = ? ,"+GsMngManager.CREATE_TIME+"= ? ,"+GsMngManager.STATUS+"= ? where "+GsMngManager.ID+ "= ? ";
			Query hq = getSession().createQuery(hql);
			hq.setLong(0,userId).setTimestamp(1,new Timestamp(new Date().getTime())).setString(2,GsMngManager.STATUS_DRAFT).setLong(3,newOrderId);
			hq.executeUpdate();
// 			gsMngDao.setEntityName(targetModel);
//			Map<String, Object> loadMap = gsMngDao.get(newOrderId);
//			loadMap.put(GsMngManager.CREATE_USER,userId );
//			loadMap.put(GsMngManager.CREATE_TIME, new Date());
//			gsMngDao.save(loadMap);			
			String updateData = userId+  "|" +newOrderId;
			execution.setVariable("childData", updateData);			
		}else{
			throw new ServiceException("找不到用户", new Exception("找不到用户"));
		}*/
		saveProcessInfo(execution.getProcessInstanceId(),execution,bid,bname);	
		
		 //保存流程下推单据信息方法	 
		String processInstanceId = execution.getProcessInstanceId();
		String executionId = execution.getId();
		for(Long masterId :listId){
			ProcessModelInfo entity = new ProcessModelInfo();
			entity.setProcessModelId(bid);
			entity.setCreateUser(userId);
			entity.setMasterId(masterId);
			entity.setModelKey(targetModel);
			entity.setProcessInstanceId(processInstanceId);
			entity.setBusinessKey(businessKey);
			entity.setExecutionId(executionId);
			entity.setCreateTime(new Date());
			processModelInfoDao.save(entity);
		}	
	}
	
	/**
	 * 根据历史任务的名称设置下推数据的创建人
	 * 
	 * @param sourceModel --- contracts.MainTable
	 * @param targetModel --- caigoushang.CaiGouShangZhuBiao1
	 * @param ruleName --- 模块.key
	 * @param taskName ---历史任务名
	 */
	@Transactional
	public void createOrderByTaskName(ActivityExecution execution,String sourceModel,String targetModel,String ruleName,String taskName){
		String businessKey = execution.getProcessBusinessKey();
		String processInstanceId = execution.getProcessInstanceId();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		Long bid = Long.valueOf(a[1]);// 单据ID
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("id",bid );
	
		HistoricTaskInstanceEntity htie =(HistoricTaskInstanceEntity) historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).taskName(taskName).singleResult();
		String loginName = htie.getAssignee();
		Long userId = null;
		if (StringUtils.isNotBlank(loginName)) {
		User user = userDao.findUniqueBy("loginName", loginName);
		userId = user.getId();
		paramMap.put("createUser",userId);
		}
		paramMap.put("status",GsMngManager.STATUS_DRAFT);
		paramMap.put("createTime",new Timestamp(new Date().getTime()));
		paramMap.put("versions",1L);
		List<Long> listId = new ArrayList<Long>();
	
		String sqlKey = Constants.RULE_SUFFIX + Constants.NAME_SPLIT_SYMBOL + ruleName;
		final String namedSql = SqlCache.getInstance().getSqlContent(sqlKey);
		if(StringUtils.isBlank(namedSql)) {
			throw new GsException(sqlKey + "对应的sql找不到");
		}
	
		listId = gsMngDao.insertDataWithReturnKeys(namedSql, paramMap);

		execution.setVariable("targetModel", targetModel);
		execution.setVariable("createUser", userId);			
		execution.setVariable("masterIdList", listId);
		
		 //保存流程下推单据信息方法	 
		String executionId = execution.getId();
		for(Long masterId :listId){
			ProcessModelInfo entity = new ProcessModelInfo();
			entity.setProcessModelId(bid);
			entity.setCreateUser(userId);
			entity.setMasterId(masterId);
			entity.setModelKey(targetModel);
			entity.setProcessInstanceId(processInstanceId);
			entity.setBusinessKey(businessKey);
			entity.setExecutionId(executionId);
			entity.setCreateTime(new Date());
			processModelInfoDao.save(entity);
		}
		saveProcessInfo(processInstanceId,execution,bid,bname);	
	}
	/**
	 * 数据下推生成子表
	 * 
	 * @param ruleName --- 模块.key
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public void createChildTable(ActivityExecution execution,String ruleName){
		String businessKey = execution.getProcessBusinessKey();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		Long bid = Long.valueOf(a[1]);
		Long createUser =  (Long)execution.getVariable("createUser");
		List<Long> masterIdList  =(List<Long>) execution.getVariable("masterIdList");
		if (masterIdList!= null) {
			final Map<String, Object> paramMap = new HashMap<String, Object>();
			for (Long masterId : masterIdList) {
				paramMap.put("id",bid );
				paramMap.put("masterId", masterId);
				paramMap.put("createUser", createUser);
				paramMap.put("createTime",
						new Timestamp(new Date().getTime()));
				paramMap.put("versions",1L);
				final List<Long> listId = new ArrayList<Long>();
				String sqlKey = Constants.RULE_SUFFIX
						+ Constants.NAME_SPLIT_SYMBOL + ruleName;
				final String namedSql = SqlCache.getInstance()
						.getSqlContent(sqlKey);
				if (StringUtils.isBlank(namedSql)) {
					throw new GsException(sqlKey + "对应的sql找不到");
				}
				Work work = new Work() {

					public void execute(Connection connection)
																throws SQLException {
						// 通过JDBC API执行用于批量更新的SQL语句
						PreparedStatement stmt = null;
						ResultSet rs = null;
						try {
							String sql = NamedParameterUtils
									.parseSqlStatementIntoString(namedSql);
							Object[] args = NamedParameterUtils
									.buildValueArray(namedSql,
											paramMap);
							stmt = connection.prepareStatement(sql,
									new String[] { "ID" });
							// stmt.setLong(1, bid);
							ArgPreparedStatementSetter aps = new ArgPreparedStatementSetter(
									args);
							aps.setValues(stmt);
							stmt.executeUpdate();
							rs = stmt.getGeneratedKeys();
							if (rs.next()) {
								Long id = (long) rs.getInt(1);
								listId.add(id);
							}
						} finally {
							if (rs != null) {
								try {
									rs.close();
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
							if (stmt != null) {
								try {
									stmt.close();
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
						}
					}
				};
				getSession().doWork(work);
			}
		}
		
		
		saveProcessInfo(execution.getProcessInstanceId(),execution,bid,bname);	
	}
	
	/**
	 * 执行sql更新
	 * 
	 * @param execution
	 * @param ruleName 多个规则用逗号隔开
	 */
	@Transactional
	public void updateData(ActivityExecution execution,String ruleName){
		String businessKey = execution.getProcessBusinessKey();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		Long bid = Long.valueOf(a[1]);// 单据ID
		
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("id",bid );
		paramMap.put("handleUserId", execution.getVariable("handleUserId"));
		String[] ruleNames = StringUtils.split(ruleName, ",");
		if(null!=ruleNames && ruleNames.length > 0) {
			for(String rn : ruleNames) {
				String sqlKey = Constants.RULE_SUFFIX + Constants.NAME_SPLIT_SYMBOL + rn;
				final String namedSql = SqlCache.getInstance().getSqlContent(sqlKey);
				if(StringUtils.isBlank(namedSql)) {
					throw new GsException(sqlKey + "对应的sql找不到");
				}
				SQLQuery sq = getSession().createSQLQuery(namedSql);
				if(null!=paramMap) {
					sq.setProperties(paramMap);
				}
				sq.executeUpdate();
			}
		}
		saveProcessInfo(execution.getProcessInstanceId(),execution,bid,bname);
	}
	/**
	 * 通过Form属性设置数据下推
	 * 
	 */
	@Transactional
	public void createOrderByForm(ActivityExecution execution,String sourceModel,String targetModel,String ruleName,String taskName){
		String businessKey = execution.getProcessBusinessKey();
		String processInstanceId = execution.getProcessInstanceId();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		Long bid = Long.valueOf(a[1]);// 单据ID
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("id",bid );
		String taskId = taskService.createTaskQuery().processInstanceId(processInstanceId).taskName(taskName).singleResult().getId();
		String loginName = (String)taskService.getVariable(taskId , "formUser");
		Long userId = null;
		if (StringUtils.isNotBlank(loginName)) {
		User user = userDao.findUniqueBy("loginName", loginName);
		userId = user.getId();
		paramMap.put("createUser",userId);
		}
		paramMap.put("status",GsMngManager.STATUS_DRAFT);
		paramMap.put("createTime",new Timestamp(new Date().getTime()));
		paramMap.put("versions",1L);
		List<Long> listId = new ArrayList<Long>();
	
		String sqlKey = Constants.RULE_SUFFIX + Constants.NAME_SPLIT_SYMBOL + ruleName;
		final String namedSql = SqlCache.getInstance().getSqlContent(sqlKey);
		if(StringUtils.isBlank(namedSql)) {
			throw new GsException(sqlKey + "对应的sql找不到");
		}
	
		listId = gsMngDao.insertDataWithReturnKeys(namedSql, paramMap);

		execution.setVariable("targetModel", targetModel);
		execution.setVariable("createUser", userId);			
		execution.setVariable("masterIdList", listId);

		saveProcessInfo(processInstanceId,execution,bid,bname);
		 //保存流程下推单据信息方法
		String executionId = execution.getId();
		for(Long masterId :listId){
			ProcessModelInfo entity = new ProcessModelInfo();
			entity.setProcessModelId(bid);
			entity.setCreateUser(userId);
			entity.setMasterId(masterId);
			entity.setModelKey(targetModel);
			entity.setProcessInstanceId(processInstanceId);
			entity.setBusinessKey(businessKey);
			entity.setExecutionId(executionId);
			entity.setCreateTime(new Date());
			processModelInfoDao.save(entity);
		}
	}
	@Transactional
	public void createOrderByStarter(ActivityExecution execution,String sourceModel,String targetModel,String ruleName){
		String businessKey = execution.getProcessBusinessKey();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		Long bid = Long.valueOf(a[1]);// 单据ID
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("id",bid );
		//设置下推数据的拥有者
	
		String	loginName= (String) execution.getVariable("startUser");
	
		User user = userDao.findUniqueBy("loginName", loginName);
		Long userId = user.getId();
		paramMap.put("createUser",userId);	
		paramMap.put("status",GsMngManager.STATUS_DRAFT);
		paramMap.put("createTime",new Timestamp(new Date().getTime()));
		paramMap.put("versions",1L);
		List<Long> listId = new ArrayList<Long>();

		String sqlKey = Constants.RULE_SUFFIX + Constants.NAME_SPLIT_SYMBOL + ruleName;
		final String namedSql = SqlCache.getInstance().getSqlContent(sqlKey);
		if(StringUtils.isBlank(namedSql)) {
			throw new GsException(sqlKey + "对应的sql找不到");
		}

		listId = gsMngDao.insertDataWithReturnKeys(namedSql, paramMap);
	
		execution.setVariable("targetModel", targetModel);
		execution.setVariable("createUser", userId);			
		execution.setVariable("masterIdList", listId);
		saveProcessInfo(execution.getProcessInstanceId(),execution,bid,bname);	
		 //保存流程下推单据信息方法	 
		String processInstanceId = execution.getProcessInstanceId();
		String executionId = execution.getId();
		for(Long masterId :listId){
			ProcessModelInfo entity = new ProcessModelInfo();
			entity.setProcessModelId(bid);
			entity.setCreateUser(userId);
			entity.setMasterId(masterId);
			entity.setModelKey(targetModel);
			entity.setProcessInstanceId(processInstanceId);
			entity.setBusinessKey(businessKey);
			entity.setExecutionId(executionId);
			entity.setCreateTime(new Date());
			processModelInfoDao.save(entity);
		}
	}
	
	/**
	 * 执行sql存过更新
	 * 
	 * @param execution
	 * @param procName 存过名字
	 */
	@Transactional
	public void callProc(ActivityExecution execution, String procName){
		String businessKey = execution.getProcessBusinessKey();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		String bid = a[1];// 单据ID
		
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("@id", bid);
		paramMap.put("@handleUserId", String.valueOf(execution.getVariable("handleUserId")));
		
		gsMngDao.callProcedure(procName, paramMap);
		
		saveProcessInfo(execution.getProcessInstanceId(),execution,Long.valueOf(bid),bname);
	}
	
	/**
	 * 执行sql存过更新，mysql
	 * 
	 * @param execution
	 * @param procName 存过名字
	 */
	@Transactional
	public void callProcForMysql(ActivityExecution execution, String procName){
		String businessKey = execution.getProcessBusinessKey();
		String a[] = businessKey.split("\\|");
		String bname = a[0];
		String bid = a[1];// 单据ID
		
		final Map<String, Object> paramMap = new HashMap<String, Object>();
		paramMap.put("inId", bid);
		paramMap.put("inHandleUserId", String.valueOf(execution.getVariable("handleUserId")));
		
		gsMngDao.callProcedure(procName, paramMap);
		
		saveProcessInfo(execution.getProcessInstanceId(),execution,Long.valueOf(bid),bname);
	}
	
	/**
	 * 保存流程信息公用方法
	 */
	public void saveProcessInfo(String pId,ActivityExecution execution ,Long entityId,String entityName){
		ProcessInfo entity = new ProcessInfo();
		entity.setProcessInstanceId(pId);
		entity.setExecutionId(execution.getId());
		entity.setDealTime(new Date());
		entity.setUserId(1L);
		entity.setDealName("系统自动处理");
		
		entity.setTaskId(execution.getId());
		entity.setTaskName(execution.getCurrentActivityName());
		entity.setBusinessId(entityId);
		entity.setBusinessName(entityName);
		entity.setActivitiId(execution.getCurrentActivityId());
		processInfoDao.save(entity);
	}
}
